37 detection rules across 10 categories and three execution tiers. Each rule is source-defined in canary/services/chirp/rule_definitions.py and loaded into the detection_rules table at seed time. Merchants adjust thresholds via merchant_rule_config.
Execution Tiers
- Tier 1 — Stateless — fires from a single webhook payload with zero lookups. Microsecond evaluation. The fast path.
- Tier 2 — Stateful — requires shift or session aggregation (e.g. refund rate by employee).
- Tier 3 — Composite — correlates multiple primary rule hits into higher-order patterns.
Cash Drawer 4 rules
Cash handling — no-sale abuse, shift variance, paid-out anomalies, after-hours drawer.
| Rule | Name | Severity | Tier | Default Threshold | Description |
|---|---|---|---|---|---|
C-104 | AFTER_HOURS_DRAWER | critical | Tier 1 — Stateless | open_hour=6, close_hour=22 | Cash drawer opened outside business hours |
C-101 | NO_SALE_ABUSE | high | Tier 1 — Stateless | count=5, window=shift | N+ no-sale drawer opens per shift |
C-102 | CASH_VARIANCE | high | Tier 1 — Stateless | amount_cents=2000 | Shift cash variance exceeds N cents |
C-103 | PAID_OUT_ANOMALY | medium | Tier 1 — Stateless | amount_cents=5000 | Paid-out exceeds N cents without manager override |
Composite 1 rules
Multi-signal rules that correlate across primary rule hits.
| Rule | Name | Severity | Tier | Default Threshold | Description |
|---|---|---|---|---|---|
C-901 | SRA_THRESHOLD_BREACH | high | Tier 1 — Stateless | sra_pct_sales_max=3.0 | Shrink Risk Assessment exceeds threshold percentage of net sales |
Dispute 3 rules
Dispute & chargeback patterns.
| Rule | Name | Severity | Tier | Default Threshold | Description |
|---|---|---|---|---|---|
C-D02 | DISPUTE_LOST | critical | Tier 1 — Stateless | — | Dispute resolved as LOST — confirmed chargeback loss |
C-D01 | DISPUTE_CREATED | high | Tier 1 — Stateless | — | New dispute filed — merchant must respond with evidence |
C-D03 | DISPUTE_VELOCITY | high | Tier 1 — Stateless | count=3, window_days=30 | N+ disputes in time window per location |
Gift Card 2 rules
Gift card abuse — load velocity, immediate drain.
| Rule | Name | Severity | Tier | Default Threshold | Description |
|---|---|---|---|---|---|
C-602 | GIFT_CARD_DRAIN | critical | Tier 1 — Stateless | seconds_after_load=1800 | Full gift card redemption immediately after load |
C-601 | GIFT_CARD_LOAD_VELOCITY | high | Tier 1 — Stateless | count=3, window_seconds=3600 | N+ gift card loads in time window (laundering signal) |
Invoice 3 rules
Invoice lifecycle anomalies.
| Rule | Name | Severity | Tier | Default Threshold | Description |
|---|---|---|---|---|---|
C-I02 | INVOICE_CHARGE_FAILED | high | Tier 1 — Stateless | — | Scheduled invoice charge failed — payment collection risk |
C-I03 | HIGH_VALUE_INVOICE_UNPAID | high | Tier 1 — Stateless | amount_cents=50000 | Unpaid invoice exceeds N cents — high-value receivable at risk |
C-I01 | INVOICE_OVERDUE | medium | Tier 1 — Stateless | — | Invoice past due date with status still UNPAID |
Loyalty 4 rules
Loyalty program integrity — rapid accumulation, bulk redemption, cross-location velocity, enrollment fraud.
| Rule | Name | Severity | Tier | Default Threshold | Description |
|---|---|---|---|---|---|
C-802 | BULK_REDEMPTION | high | Tier 1 — Stateless | points=5000 | Points redeemed exceed N in single event |
C-803 | CROSS_LOCATION_VELOCITY | high | Tier 1 — Stateless | location_count=3, window_seconds=7200 | Loyalty events at N+ locations in time window |
C-801 | RAPID_POINT_ACCUMULATION | medium | Tier 1 — Stateless | count=5, window_seconds=3600 | N+ loyalty point events in time window |
C-804 | ENROLLMENT_FRAUD | medium | Tier 1 — Stateless | count=10, window_seconds=86400 | N+ loyalty enrollments from same employee in time window |
Order 4 rules
Order & line-item patterns — excessive discount rates, void rates, sweethearting.
| Rule | Name | Severity | Tier | Default Threshold | Description |
|---|---|---|---|---|---|
C-204 | UNTENDERED_ORDER | critical | Tier 1 — Stateless | stale_hours=24 | Order created with no corresponding payment after threshold hours (sweethearting/open-ticket drift) |
C-201 | EXCESSIVE_DISCOUNT_RATE | high | Tier 1 — Stateless | percent=50 | Average order discount exceeds N% (sweethearting signal) |
C-202 | LINE_ITEM_VOID_RATE | high | Tier 1 — Stateless | percent=10, min_items=10 | Employee line item void rate exceeds N% |
C-203 | SWEETHEARTING | high | Tier 1 — Stateless | amount_cents=2000 | Discount applied without manager approval on high-value item |
Payment 11 rules
Transaction-level anomalies — refunds, voids, card velocity, after-hours, manual entry.
| Rule | Name | Severity | Tier | Default Threshold | Description |
|---|---|---|---|---|---|
C-009 | SQUARE_DELAY_HOLD | critical | Tier 1 — Stateless | — | Square has flagged this payment with a delay action — money is being held |
C-001 | RAPID_REFUND | high | Tier 1 — Stateless | seconds=900 | Refund issued within N seconds of original sale |
C-002 | EXCESSIVE_REFUND_RATE | high | Tier 1 — Stateless | percent=15, min_transactions=5 | Employee refund rate exceeds N% of total transactions in shift |
C-005 | CARD_VELOCITY | high | Tier 1 — Stateless | count=5, window_seconds=3600 | Same card fingerprint used N+ times in time window |
C-007 | HIGH_VALUE_REFUND | high | Tier 1 — Stateless | amount_cents=10000 | Single refund exceeds N cents |
C-010 | PARTIAL_AUTHORIZATION | high | Tier 1 — Stateless | variance_cents=0 | Bank approved less than requested — partial authorization signal |
C-011 | NO_SALE_DETECTED | high | Tier 1 — Stateless | — | Payment flagged as NO_SALE — cash drawer opened with no transaction |
C-003 | ROUND_AMOUNT_PATTERN | medium | Tier 1 — Stateless | count=5, window_seconds=3600 | N+ round-dollar transactions in time window (structuring signal) |
C-004 | AFTER_HOURS_TRANSACTION | medium | Tier 1 — Stateless | open_hour=6, close_hour=22 | Transaction processed outside configured business hours |
C-006 | SPLIT_TENDER_PATTERN | medium | Tier 1 — Stateless | count=3, window_seconds=3600 | N+ split-tender transactions in time window (structuring signal) |
C-008 | MANUAL_ENTRY_SPIKE | medium | Tier 1 — Stateless | count=5, window=shift | N+ keyed-in card transactions per shift (card-not-present risk) |
Timecard 3 rules
Clock-in integrity — off-clock transactions, break transactions, cross-location activity.
| Rule | Name | Severity | Tier | Default Threshold | Description |
|---|---|---|---|---|---|
C-301 | OFF_CLOCK_TRANSACTION | critical | Tier 1 — Stateless | — | Payment processed by employee with no open timecard (ghost employee) |
C-302 | BREAK_TRANSACTION | high | Tier 1 — Stateless | — | Payment processed during employee declared break window |
C-303 | WRONG_LOCATION | high | Tier 1 — Stateless | — | Employee clocked in at Location A but payment at Location B |
Void 2 rules
Void patterns — high void rates, post-void alerts.
| Rule | Name | Severity | Tier | Default Threshold | Description |
|---|---|---|---|---|---|
C-502 | POST_VOID_ALERT | critical | Tier 1 — Stateless | immediate_max_seconds=120, watch_max_seconds=900, suspicious_max_seconds=28800, self_refund_score_boost=10, off_clock_score_boost=15 | Full refund of completed sale — tiered by time gap. WATCH (2-15 min), SUSPICIOUS (15 min - 8 hr). Self-refund by same employee boosts risk. |
C-501 | HIGH_VOID_RATE | high | Tier 1 — Stateless | count=5, window=shift | N+ voids per shift (concealment technique) |
Source of Truth
This catalog is generated from canary/services/chirp/rule_definitions.py. To propose a new rule or change a threshold, edit the dataclass definition; the seed pipeline and this catalog both pick it up on the next build.